package com.itheima.aop;

import com.itheima.bean.Student;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

import java.util.Arrays;

//通知类，告诉spring在增强的前后需要做什么事
public class Advice {
    /**
     * 参数为连接点对象
     * @param jp
     */
    public void before(JoinPoint jp){
        //获取方法参数
        Object[] args = jp.getArgs();
        System.out.println(Arrays.toString(args));
        //前置通知：开启事务
        System.out.println("前置通知：开启事务");
    }

    public void afterReturn(Object result){
        System.out.println("result = " + result);
        if(result instanceof Student){
            Student student= (Student) result;
            student.setName("郑志颖");
        }
        //后置通知：提交事务
        System.out.println("后置通知：提交事务");
    }

    public void afterThrowable(Throwable e){
        //异常通知：回滚事务
        System.out.println("异常通知：回滚事务"+e.getMessage());
    }

    public void after(){
        //最终通知：释放资源
        System.out.println("最终通知：释放资源");
    }

    /**
     * 定义环绕通知,手动调用目标对象的方法和通知方法。
     * ProceedingJoinPoint pjp :封装了被拦截到的方法，也就是连接点方法，但是不一定被增强，是否被增强取决于around方法中的代码属性
     */
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        //System.out.println("环绕通知执行了。。。");
        /*Object[] args = pjp.getArgs(); //获取方法参数
        System.out.println(Arrays.toString(args));

        Object obj = pjp.getTarget(); //获取目标对象
        System.out.println("obj = " + obj);*/

        String methodName = pjp.getSignature().getName(); //获取目标方法名称
        System.out.println("methodName = " + methodName);

        Object value = null;
        try {
            //前置增强
            //before();
            long start = System.currentTimeMillis();
            //执行目标方法
            value = pjp.proceed();// 相当于 value = method.invoke(studentService, args);
            //后置增强
            //afterReturn();
            long end = System.currentTimeMillis();
            System.out.println(methodName+"耗时："+(end-start));
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            //异常增强
            //afterThrowable();
        } finally {
            //最终增强
            after();
        }
        return value;
    }
}
